package com.zenithmind.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.cache.DataCacheEvict;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.user.mapper.TenantMapper;
import com.zenithmind.user.pojo.domain.Role;
import com.zenithmind.user.pojo.domain.Tenant;
import com.zenithmind.user.pojo.domain.User;
import com.zenithmind.user.pojo.domain.UserRole;
import com.zenithmind.user.pojo.dto.TenantCreateDTO;
import com.zenithmind.user.pojo.query.TenantQuery;
import com.zenithmind.user.pojo.vo.TenantVO;
import com.zenithmind.user.service.RoleService;
import com.zenithmind.user.service.TenantService;
import com.zenithmind.user.service.UserRoleService;
import com.zenithmind.user.service.UserService;
import com.zenithmind.user.utils.PasswordUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 租户服务实现类
 * 
 * @author ZenithMind
 * @since 2024-06-30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements TenantService {

    private final UserService userService;
    private final RoleService roleService;
    private final UserRoleService userRoleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<TenantVO> createTenant(TenantCreateDTO createDTO) {
        log.info("创建租户: {}", createDTO.getTenantCode());

        // 检查租户编码是否已存在
        if (existsByTenantCode(createDTO.getTenantCode())) {
            return Result.fail(ResultCode.CONFLICT, "租户编码已存在");
        }

        try {
            // 创建租户
            Tenant tenant = new Tenant();
            BeanUtils.copyProperties(createDTO, tenant);
            tenant.setStatus(Tenant.TenantStatus.ENABLED.getCode());
            tenant.setCurrentUsers(0);
            tenant.setStorageUsed(0L);
            
            if (!save(tenant)) {
                return Result.fail(ResultCode.FAIL, "创建租户失败");
            }

            // 初始化租户数据
            initTenantData(tenant, createDTO);

            TenantVO tenantVO = convertToVO(tenant);
            log.info("租户创建成功: {}", tenant.getTenantCode());
            return Result.success(tenantVO);

        } catch (Exception e) {
            log.error("创建租户失败", e);
            return Result.fail(ResultCode.FAIL, "创建租户失败: " + e.getMessage());
        }
    }

    @Override
    @DataCache(prefix = "tenant:page", key = "#query.toString()", expireTime = 1800)
    public PageResult<TenantVO> getTenantPage(TenantQuery query) {
        Page<Tenant> page = query.toPage();
        Page<Tenant> result = lambdaQuery()
                .like(StringUtils.hasText(query.getTenantCode()), Tenant::getTenantCode, query.getTenantCode())
                .like(StringUtils.hasText(query.getTenantName()), Tenant::getTenantName, query.getTenantName())
                .eq(query.getTenantType() != null, Tenant::getTenantType, query.getTenantType())
                .page(page);
        
        // 将Tenant转换为TenantVO并计算额外信息
        List<TenantVO> records = result.getRecords().stream()
                .map(this::convertToVO)
                .peek(this::calculateTenantInfo)
                .collect(Collectors.toList());
        
        return PageResult.of(records, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @DataCache(prefix = "tenant", key = "#id", expireTime = 3600)
    public TenantVO getTenantById(String id) {
        if (!StringUtils.hasText(id)) {
            return null;
        }

        Tenant tenant = getById(id);
        if (tenant == null) {
            return null;
        }

        TenantVO tenantVO = convertToVO(tenant);
        calculateTenantInfo(tenantVO);
        return tenantVO;
    }

    @Override
    @DataCache(prefix = "tenant:code", key = "#tenantCode", expireTime = 3600)
    public TenantVO getTenantByCode(String tenantCode) {
        if (!StringUtils.hasText(tenantCode)) {
            return null;
        }

        Tenant tenant = baseMapper.selectByTenantCode(tenantCode);
        if (tenant == null) {
            return null;
        }

        TenantVO tenantVO = convertToVO(tenant);
        calculateTenantInfo(tenantVO);
        return tenantVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = "tenant", key = "#tenant.id")
    public Result<TenantVO> updateTenant(Tenant tenant) {
        if (!StringUtils.hasText(tenant.getId())) {
            return Result.fail(ResultCode.INVALID_PARAM, "租户ID不能为空");
        }

        // 检查租户是否存在
        Tenant existingTenant = getById(tenant.getId());
        if (existingTenant == null) {
            return Result.fail(ResultCode.NOT_FOUND, "租户不存在");
        }

        // 如果修改了租户编码，检查是否重复
        if (!existingTenant.getTenantCode().equals(tenant.getTenantCode())) {
            if (existsByTenantCode(tenant.getTenantCode())) {
                return Result.fail(ResultCode.CONFLICT, "租户编码已存在");
            }
        }

        if (updateById(tenant)) {
            TenantVO tenantVO = convertToVO(tenant);
            calculateTenantInfo(tenantVO);
            return Result.success(tenantVO);
        }

        return Result.fail(ResultCode.FAIL, "更新租户失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = "tenant", key = "#id")
    public Result<Void> updateTenantStatus(String id, Integer status) {
        if (!StringUtils.hasText(id)) {
            return Result.fail(ResultCode.INVALID_PARAM, "租户ID不能为空");
        }

        Tenant tenant = getById(id);
        if (tenant == null) {
            return Result.fail(ResultCode.NOT_FOUND, "租户不存在");
        }

        tenant.setStatus(status);
        if (updateById(tenant)) {
            log.info("租户状态更新成功: {} -> {}", id, status);
            return Result.success();
        }

        return Result.fail(ResultCode.FAIL, "更新租户状态失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = "tenant", key = "#id")
    public Result<Void> deleteTenant(String id) {
        if (!StringUtils.hasText(id)) {
            return Result.fail(ResultCode.INVALID_PARAM, "租户ID不能为空");
        }

        // 检查是否为默认租户
        if ("default".equals(id)) {
            return Result.fail(ResultCode.FORBIDDEN, "不能删除默认租户");
        }

        Tenant tenant = getById(id);
        if (tenant == null) {
            return Result.fail(ResultCode.NOT_FOUND, "租户不存在");
        }

        // 检查租户下是否还有用户
        if (tenant.getCurrentUsers() > 0) {
            return Result.fail(ResultCode.FORBIDDEN, "租户下还有用户，不能删除");
        }

        if (removeById(id)) {
            log.info("租户删除成功: {}", id);
            return Result.success();
        }

        return Result.fail(ResultCode.FAIL, "删除租户失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> deleteTenantBatch(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return Result.fail(ResultCode.INVALID_PARAM, "租户ID列表不能为空");
        }

        // 检查是否包含默认租户
        if (ids.contains("default")) {
            return Result.fail(ResultCode.FORBIDDEN, "不能删除默认租户");
        }

        // 检查租户下是否还有用户
        for (String id : ids) {
            Tenant tenant = getById(id);
            if (tenant != null && tenant.getCurrentUsers() > 0) {
                return Result.fail(ResultCode.FORBIDDEN, "租户 " + tenant.getTenantName() + " 下还有用户，不能删除");
            }
        }

        if (removeByIds(ids)) {
            log.info("批量删除租户成功: {}", ids);
            return Result.success();
        }

        return Result.fail(ResultCode.FAIL, "批量删除租户失败");
    }

    @Override
    public List<TenantVO> getExpiringSoonTenants() {
        return baseMapper.selectExpiringSoonTenants();
    }

    @Override
    public List<TenantVO> getExpiredTenants() {
        return baseMapper.selectExpiredTenants();
    }

    @Override
    public boolean updateUserCount(String tenantId, Integer userCount) {
        return baseMapper.updateUserCount(tenantId, userCount) > 0;
    }

    @Override
    public boolean updateStorageUsed(String tenantId, Long storageUsed) {
        return baseMapper.updateStorageUsed(tenantId, storageUsed) > 0;
    }

    @Override
    public boolean incrementStorageUsed(String tenantId, Long increment) {
        return baseMapper.incrementStorageUsed(tenantId, increment) > 0;
    }

    @Override
    public boolean existsByTenantCode(String tenantCode) {
        if (!StringUtils.hasText(tenantCode)) {
            return false;
        }
        return baseMapper.selectByTenantCode(tenantCode) != null;
    }

    @Override
    @DataCache(prefix = "tenant:valid", key = "#tenantId", expireTime = 1800)
    public boolean isTenantValid(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            return false;
        }

        Tenant tenant = getById(tenantId);
        if (tenant == null) {
            return false;
        }

        // 检查租户状态
        if (!Tenant.TenantStatus.ENABLED.getCode().equals(tenant.getStatus())) {
            return false;
        }

        // 检查是否过期
        if (tenant.getExpireTime() != null && tenant.getExpireTime().isBefore(LocalDateTime.now())) {
            return false;
        }

        return true;
    }

    @Override
    public TenantVO getTenantStats() {
        // 这里可以实现租户统计逻辑
        // 比如总租户数、活跃租户数、即将到期租户数等
        return new TenantVO();
    }

    /**
     * 初始化租户数据
     */
    private void initTenantData(Tenant tenant, TenantCreateDTO createDTO) {
        // 创建租户管理员用户
        if (StringUtils.hasText(createDTO.getAdminUsername())) {
            createTenantAdmin(tenant, createDTO);
        }

        // 创建默认角色
        createDefaultRoles(tenant);

        log.info("租户数据初始化完成: {}", tenant.getTenantCode());
    }

    /**
     * 创建租户管理员
     */
    private void createTenantAdmin(Tenant tenant, TenantCreateDTO createDTO) {
        // 这里需要临时设置租户上下文，以便创建的用户属于正确的租户
        // 实际实现中可能需要更复杂的处理
        User adminUser = new User();
        adminUser.setTenantId(tenant.getId());
        adminUser.setUsername(createDTO.getAdminUsername());
        adminUser.setPassword(PasswordUtils.encryption(createDTO.getAdminPassword()));
        adminUser.setEmail(createDTO.getAdminEmail());
        adminUser.setNickname("管理员");
        adminUser.setStatus(1);
        
        // 保存用户（这里简化处理，实际应该调用UserService）
        // userService.save(adminUser);
        
        log.info("租户管理员创建完成: {}", createDTO.getAdminUsername());
    }

    /**
     * 创建默认角色
     */
    private void createDefaultRoles(Tenant tenant) {
        // 创建管理员角色
        Role adminRole = new Role();
        adminRole.setTenantId(tenant.getId());
        adminRole.setRoleName("管理员");
        adminRole.setRoleCode("ADMIN");
        adminRole.setDescription("租户管理员角色");
        adminRole.setStatus(1);
        
        // 创建普通用户角色
        Role userRole = new Role();
        userRole.setTenantId(tenant.getId());
        userRole.setRoleName("普通用户");
        userRole.setRoleCode("USER");
        userRole.setDescription("普通用户角色");
        userRole.setStatus(1);
        
        // 保存角色（这里简化处理，实际应该调用RoleService）
        // roleService.save(adminRole);
        // roleService.save(userRole);
        
        log.info("默认角色创建完成");
    }

    /**
     * 转换为VO对象
     */
    private TenantVO convertToVO(Tenant tenant) {
        TenantVO vo = new TenantVO();
        BeanUtils.copyProperties(tenant, vo);
        
        // 设置类型名称
        if (tenant.getTenantType() != null) {
            for (Tenant.TenantType type : Tenant.TenantType.values()) {
                if (type.getCode().equals(tenant.getTenantType())) {
                    vo.setTenantTypeName(type.getName());
                    break;
                }
            }
        }
        
        // 设置状态名称
        if (tenant.getStatus() != null) {
            for (Tenant.TenantStatus status : Tenant.TenantStatus.values()) {
                if (status.getCode().equals(tenant.getStatus())) {
                    vo.setStatusName(status.getName());
                    break;
                }
            }
        }
        
        return vo;
    }

    /**
     * 计算租户额外信息
     */
    private void calculateTenantInfo(TenantVO tenantVO) {
        // 计算存储使用率
        if (tenantVO.getStorageQuota() != null && tenantVO.getStorageQuota() > 0) {
            double usageRate = (double) tenantVO.getStorageUsed() / tenantVO.getStorageQuota() * 100;
            tenantVO.setStorageUsageRate(Math.round(usageRate * 100.0) / 100.0);
        }
        
        // 格式化存储大小
        tenantVO.setStorageQuotaFormatted(formatFileSize(tenantVO.getStorageQuota()));
        tenantVO.setStorageUsedFormatted(formatFileSize(tenantVO.getStorageUsed()));
        
        // 计算剩余天数
        if (tenantVO.getExpireTime() != null) {
            long days = ChronoUnit.DAYS.between(LocalDateTime.now(), tenantVO.getExpireTime());
            tenantVO.setRemainingDays(days);
            tenantVO.setIsExpiringSoon(days <= 7 && days >= 0);
        }
    }

    /**
     * 格式化文件大小
     */
    private String formatFileSize(Long size) {
        if (size == null || size == 0) {
            return "0 B";
        }
        
        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double fileSize = size.doubleValue();
        
        while (fileSize >= 1024 && unitIndex < units.length - 1) {
            fileSize /= 1024;
            unitIndex++;
        }
        
        return String.format("%.2f %s", fileSize, units[unitIndex]);
    }
}
